package cn.kmsoft.jssc.service.processor;

import java.util.*;

import cn.kmsoft.jssc.config.AnalyseConfig;
import cn.kmsoft.jssc.entity.analyse.*;
import cn.kmsoft.jssc.service.AnalyseTaskProcessor;
import cn.kmsoft.common.utils.StringUtil;
import cn.kmsoft.wololo.object.query.GeoJsonQuery;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;


/**
 * 通用数据-空间套合叠加分析，不做二级三级汇总，保持详细地块的原样输出
 *
 * @author wangq 2023-12-18
 *
 */
public class CommonAnalyseTaskProcessor extends AnalyseTaskProcessor {
  private static final Logger logger = LoggerFactory.getLogger(YjjbntAnalyseTaskProcessor.class);
  //基本农田
  private final String analysePoint="common";
  private AnalyseTaskParam analyseTaskParam;
  private AnalyseConfig analyseConfig;

  public CommonAnalyseTaskProcessor(AnalyseTaskParam param, AnalyseConfig analyseConfig) {
    this.analyseTaskParam=param;
    this.analyseConfig=analyseConfig;
  }

  public AnalyseTaskParam getAnalyseTaskParam() {
    return analyseTaskParam;
  }
  public void setAnalyseTaskParam(AnalyseTaskParam analyseTaskParam) {
    this.analyseTaskParam = analyseTaskParam;
  }

  @Override
  public TaskResult call() throws Exception {
    // TODO Auto-generated method stub
    String threadId = Thread.currentThread().getName();

    String tableName = this.analyseTaskParam.getTableName();
    String analyseType=this.analyseTaskParam.getAnalystType();
    String dbKey = this.analyseTaskParam.getDbKey();
    int fgeo_wkid= this.analyseTaskParam.getFgeo_wkid();
    String feaTypePoint = analyseTaskParam.getFeaTypePoint();

    AnalyseDb analyseDb = this.analyseConfig.getAnalyseDbByDbkey(dbKey);
    if(analyseDb==null){
      System.out.println();
      String errorMsg = String.format("--->TaskProcessor stop, dbKey: %s, 为null",dbKey);
      System.out.println(errorMsg);
      logger.warn(errorMsg);

      return null;
    }
    String dbType = analyseDb.getDbType();
    String dbInstance = analyseDb.getDbInstance();
    String tablespace = analyseDb.getTablespace();
    String serverId = analyseDb.getServerId();//分析服务标识

    String tableId = dbInstance + "/" + tablespace + "." + tableName;
    //注意，根据数据库类型进行分类处置。
    //若为oracle的sde，则需要添加表空间；
    if("postgresql".equalsIgnoreCase(dbType)){
      //若为postgresql的postgis库，则去掉表空间或者为postgis_33_sample.sde.dltb_2018_500155_d36
      //tableId = dbInstance + "/" + dbInstance+"."+ tablespace + "." + tableName;
      tableId = dbInstance + "/" + tableName;
    }

    String operatorMethod = "intersectpy";
    if(analyseType.equalsIgnoreCase("intersect") && feaTypePoint.equalsIgnoreCase("py")){
      operatorMethod = "intersectpy";
    }else if(analyseType.equalsIgnoreCase("intersect") && feaTypePoint.equalsIgnoreCase("py2")){
      operatorMethod = "intersectpy2";
    }else if(analyseType.equalsIgnoreCase("spatialquery") && feaTypePoint.equalsIgnoreCase("py")){
      operatorMethod = "spatialQuery";
    } else if(analyseType.equalsIgnoreCase("spatialquery") && feaTypePoint.equalsIgnoreCase("py2")){
      operatorMethod = "spatialQuery2";
    } else if(analyseType.equalsIgnoreCase("difference") && feaTypePoint.equalsIgnoreCase("py")){
      operatorMethod = "difference";
    }

    AnalyseServer analyseServer = this.analyseConfig.getAnalyseServerByServerId(serverId);
    String serverUrl = analyseServer.getServerUrl();

    String targetUrl = serverUrl + "/" + operatorMethod + "/" + tableId;
    //String targetUrl = this.analyseConfig.getServerUrl() + "/" + operatorMethod + "/" + tableId;
    //String targetUrl = this.analyseConfig.getServerUrl() + "/" + analyseType + "/" + tableId;

    //任务参数
    AnalyseTaskParam params = this.analyseTaskParam;
    params.setTargetUrl(targetUrl);

    TaskResult taskResult = this.startAnalyse(operatorMethod,threadId, params);

    return taskResult;
  }

  /**
   * start分析
   *
   * TaskParam params
   * Return
   */
  @Override
  public TaskResult startAnalyse(String operatorMethod, String threadId, AnalyseTaskParam params) {
    TaskResult result = new TaskResult();

    String tableName= params.getTableName();
    String targetUrl = params.getTargetUrl();
    String jobId= params.getJobId();
    String taskId = params.getTaskId();
    String dkbh = params.getDkbh();
    GeoJsonQuery query = (GeoJsonQuery) params.getQuery();

    result.setThreadId(threadId);
    result.setJobId(jobId);
    result.setAnalystPoint(this.analysePoint);
    result.setProcessorName(params.getProcessName());
    result.setTaskId(taskId);
    result.setDkbh(dkbh);
    result.setTableName(tableName);

    System.out.println(String.format("--->doAnalyse,threadId: %s, jobId: %s, dkbh: %s, targetUrl: %s",threadId, jobId, dkbh, targetUrl));
    //叠加分析
    List<CommonDetailResult> commonDetailList = this.doAnalyse(jobId,targetUrl, query);
    if(commonDetailList.size()>0){
      CommonDetailResult detailResult=commonDetailList.get(0);
      double sgeoarea = detailResult.getSgeoarea();
      result.setDkmj(sgeoarea);
    }

    System.out.println(String.format("--->threadId: %s, jobId: %s, analysePoint: %s, 通用占压分析的详细数量： %d", threadId, jobId,  this.analysePoint, commonDetailList.size()));

    result.setDetailsListResult(commonDetailList);
    result.setSummary03Result(null);
    result.setSummary03DBEntResult(null);
    result.setSummary02Result(null);
    result.setSummary01Result(null);

    return result;
  }


  /**
   * 永久基本农田-占用分析
   *
   * @param query
   * @return
   */
  public List<CommonDetailResult> doAnalyse(String jobId, String targetUrl, GeoJsonQuery query) {

    List<CommonDetailResult> commonDetailList = new ArrayList<CommonDetailResult>();

    String queryJsonStr = JSONObject.toJSONString(query);
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);

    HttpEntity<String> entity = new HttpEntity<>(queryJsonStr, headers);

    //2、转发空间分析的请求
    ResponseEntity<JSONObject> exchange = this.exchangeSpatialAnalyst(jobId, targetUrl, entity);
    if(exchange==null){
      logger.error("转发后台spatialboot的请求发生异常，exchangeSpatialAnalyst返回为null");
      return commonDetailList;
    }
    JSONObject jbntObject= exchange.getBody();
    if(jbntObject==null || jbntObject.getJSONArray("result")==null) {
      logger.error("转发后台spatialboot返回结果为空");
      return commonDetailList;
    }

    JSONArray feasJSONArray =jbntObject.getJSONArray("result").getJSONObject(0).getJSONArray("features");
    //仅仅获取属性
    //List<Map<String,String>> allFeaProperties = this.parseFeaProperties(feasJSONArray);
    //获取图形和属性
    List<Map<String,String>> allFeaProperties = this.parseFeaGeometryAndProperties(feasJSONArray);
    int feaCount = allFeaProperties.size();
    for(int i=0; i<feaCount; i++ ) {
      Map<String,String> feaProps = allFeaProperties.get(i);

      //将要素属性的key全部转为小写，否则oracle和postgresql数据库返回的结果会有差异
      Map<String,String> feaPropsKeyLowercCase = new HashMap<>();
      feaProps.forEach((key,value) -> feaPropsKeyLowercCase.put(key.toLowerCase(), value));

      //1-追加的3个几何面积
      double area = Double.parseDouble(feaPropsKeyLowercCase.get("area") != null ? feaPropsKeyLowercCase.get("area").toString() : "0.0");//叠加后重叠范围的几何面积
      double fgeoarea = Double.parseDouble(feaPropsKeyLowercCase.get("fgeoarea") != null ? feaPropsKeyLowercCase.get("fgeoarea").toString(): "0.0");//目标图层（sde库）原图斑几何面积
      double sgeoarea = Double.parseDouble(feaPropsKeyLowercCase.get("sgeoarea") != null ? feaPropsKeyLowercCase.get("sgeoarea").toString(): "0.0");//上传图斑的几何面积

      //2-叠加相交结果的几何图形
      String geomText = feaPropsKeyLowercCase.get("geom").toString();


      CommonDetailResult commonDetail = new CommonDetailResult();
      //新增的几何面积
      commonDetail.setFgeoarea(Math.abs(fgeoarea));//目标图层（sde库）原图斑几何面积
      commonDetail.setSgeoarea(Math.abs(sgeoarea));//上传图斑几何面积
      commonDetail.setArea( Math.abs(area) );	//套合相交几何面积

      commonDetail.setGeomText(geomText);//图形
      //其他详细字段信息
      commonDetail.setFeaProps(feaProps);

      commonDetailList.add(commonDetail);
    }

    return commonDetailList;
  }


}
